package root

import (
	"fmt"
	"goProject/api/auth"
	"goProject/db"
	"goProject/table"
	"net/http"
	"sync"

	"gorm.io/gorm"

	"gitee.com/ruige_fun/util/std"
	"github.com/kataras/iris/v12"
)

// resetCASBIN 重新建立权限列表，菜单列表；一般修改了角色权限后，需要执行一下本功能
func resetCASBIN(c iris.Context) {
	_ = auth.RoleMenuCache.ClearAll() //清空所有的菜单列表缓存
	auth.AutoAddPolicy()              //重新建立请求权限列表
	c.JSON(std.NewResp(http.StatusOK, "", nil, nil))
}

// roleList 获取所有的普通角色列表
func roleList(c iris.Context) {
	var result = make([]table.Role, 0)
	db.MySQL.Where("`id` > ?", 0).Order("`id` DESC").Find(&result)
	c.JSON(std.NewResp(http.StatusOK, "", result, len(result)))
}

type pRoleMenuByRoleID struct {
	ID uint `json:"id" validate:"required,min=2"` //只能修改权限角色ID，大于 2 的菜单权限。
}

// roleMenuByRoleID 获取指定角色的菜单权限列表，有权和无权的全部。
func roleMenuByRoleID(c iris.Context) {
	var p pRoleMenuByRoleID
	err := c.ReadQuery(&p)
	if err != nil {
		c.JSON(std.NewResp(http.StatusBadRequest, "参数校验失败", nil, nil))
		return
	}

	var result = make([]table.MenuDir, 0)
	db.MySQL.Where("`id` > ?", 2).Preload("Items").Find(&result)
	var allItem []table.RoleMenuItem //获取当前角色，拥有的所有菜单项（页面）
	db.MySQL.Where("`role_id` = ?", p.ID).Find(&allItem)
	var have = sync.Map{} //记录当前角色，拥有的菜单项（页面）ID
	for _, d := range allItem {
		have.Store(fmt.Sprint(d.MenuItemID), byte(0))
	}

	var rTrue = true
	var rFalse = false
	if p.ID <= 2 {
		rFalse = true
	}
	for i := 0; i < len(result); i++ {
		for j := 0; j < len(result[i].Items); j++ {
			if _, ok := have.Load(fmt.Sprint(result[i].Items[j].ID)); ok {
				result[i].Items[j].RoleMenuItem = &rTrue
			} else {
				result[i].Items[j].RoleMenuItem = &rFalse
			}
		}
	}
	c.JSON(std.NewResp(http.StatusOK, "", result, len(result)))
}

type pRoleMenuSaveByRoleID struct {
	ID   uint            `json:"id" validate:"required,min=1"`
	List []table.MenuDir `json:"list" validate:"required,min=1"`
}

// roleMenuSaveByRoleID 保存指定角色的菜单权限列表，有权和无权的全部。
func roleMenuSaveByRoleID(c iris.Context) {
	var p pRoleMenuSaveByRoleID
	err := c.ReadJSON(&p)
	if err != nil {
		c.JSON(std.NewResp(http.StatusBadRequest, "读取保存内容失败", nil, nil))
		return
	}
	if p.ID <= 2 {
		c.JSON(std.NewResp(http.StatusBadRequest, "ROOT用户和ADMIN用户权限是固定的，禁止修改。", nil, nil))
		return
	}
	err = db.MySQL.Transaction(func(tx *gorm.DB) error {
		err2 := tx.Where("`role_id` = ?", p.ID).Delete(&table.RoleMenuItem{}).Error
		if err2 != nil {
			return err2
		}
		for _, d := range p.List {
			for _, it := range d.Items {
				if it.RoleMenuItem != nil && *it.RoleMenuItem == true {
					err2 = tx.Create(&table.RoleMenuItem{
						RoleID:     p.ID,
						MenuItemID: it.ID,
					}).Error
					if err2 != nil {
						return err2
					}
				}
			}
		}
		return nil
	})
	if err != nil {
		c.JSON(std.NewResp(http.StatusBadRequest, "保存权限列表失败", nil, nil))
		return
	}
	_ = auth.RoleMenuCache.Del(fmt.Sprint(p.ID)) //删除掉权限角色 p.ID 的菜单缓存
	c.JSON(std.NewResp(http.StatusOK, "", nil, nil))
}

type pRoleCreate struct {
	Key  string `json:"key" validate:"required,min=1,max=50"`
	Name string `json:"name" validate:"required,min=1,max=255"`
}

// roleCreate 创建新的角色
func roleCreate(c iris.Context) {
	var p pRoleCreate
	err := c.ReadJSON(&p)
	if err != nil {
		c.JSON(std.NewResp(http.StatusBadRequest, "参数校验失败", nil, nil))
		return
	}
	var item table.Role
	db.MySQL.Where("`key` = ?", p.Key).First(&item)
	if item.ID > 0 {
		c.JSON(std.NewResp(http.StatusBadRequest, fmt.Sprint("创建失败：", p.Key, "已存在。"), nil, nil))
		return
	}
	err = db.MySQL.Create(&table.Role{
		Key:  p.Key,
		Name: p.Name,
	}).Error
	if err != nil {
		c.JSON(std.NewResp(http.StatusInternalServerError, fmt.Sprint("创建失败，保存到数据失败：", err), nil, nil))
		return
	}
	c.JSON(std.NewResp(http.StatusOK, "", nil, nil))
}
